package com.ltcode.config;

import com.ltcode.assistant.ChatAssistant;
import com.ltcode.listener.ChatModeCustomerListener;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.chat.StreamingChatModel;
import dev.langchain4j.model.chat.listener.ChatModelListener;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
import dev.langchain4j.service.AiServices;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;

/**
 * @Description: 知识出处 https://docs.langchain4j.dev/get-started
 */
@Configuration
public class LLMConfig {
    /**
     * langchain4j 原生配置
     * 多模型配置
     *
     * @return
     */
    @Bean(name = "qwen")
    public ChatModel chatModelQwen() {
        /**
         * OpenAiChatModelBuilder
         * httpClientBuilder：HTTP客户端构建器，用于自定义HTTP客户端配置，如连接超时、线程池等。
         * baseUrl：API的基础URL地址，用于指定OpenAI或其他兼容API的服务地址。
         * apiKey：API密钥，用于身份验证和访问API服务的凭证。
         * organizationId：组织ID，用于指定OpenAI组织，当账户属于多个组织时使用。
         * projectId：项目ID，用于区分不同的项目，便于资源管理和计费。
         * defaultRequestParameters：默认请求参数，为所有请求设置通用的参数配置。
         * modelName：模型名称，指定要使用的具体AI模型，如"gpt-3.5-turbo"、"qwen-plus"等。
         * temperature：温度值，控制输出的随机性，范围通常在0-2之间。值越高结果越随机多样，值越低结果越确定。
         * topP：核采样参数，控制输出token的概率阈值。只考虑累积概率达到此值的token，用于平衡生成文本的质量和多样性。
         * stop：停止词列表，当模型生成这些词时会停止生成，用于控制输出的结束位置。
         * maxTokens：最大token数，限制模型生成的最大token数量，控制输出长度。
         * maxCompletionTokens：最大完成token数，专门用于限制完成内容的最大token数量。
         * presencePenalty：存在惩罚，用于减少重复主题或内容，值越高越鼓励模型讨论新话题。
         * frequencyPenalty：频率惩罚，用于减少重复词汇，值越高越会惩罚出现频率高的词汇。
         * logitBias：logit偏差，用于修改特定token的生成概率，可以手动调整某些词的出现概率。
         * supportedCapabilities：支持的功能集合，指定模型支持的能力，如工具调用、并行函数调用等。
         * responseFormat：响应格式，指定返回结果的格式，如"text"或"json_object"。
         * strictJsonSchema：严格的JSON模式，控制是否严格按照JSON模式生成输出。
         * seed：种子值，用于控制生成的随机性，相同种子值会产生相同的结果，实现可重现输出。
         * user：用户标识符，用于标识最终用户，便于检测和防止滥用。
         * strictTools：严格工具模式，控制工具调用是否严格按照定义执行。
         * parallelToolCalls：并行工具调用，控制是否允许模型同时调用多个工具。
         * store：存储标志，指示是否将对话存储用于训练或其他目的。
         * metadata：元数据，附加的键值对信息，用于传递额外的上下文。
         * serviceTier：服务层级，指定使用的服务等级，可能影响性能和价格。
         * timeout：超时时间，设置API请求的超时时间。
         * maxRetries：最大重试次数，当请求失败时的最大重试次数。
         * logRequests：请求日志，控制是否记录发送的请求信息。
         * logResponses：响应日志，控制是否记录接收到的响应信息。
         * customHeaders：自定义请求头，用于添加额外的HTTP请求头信息。
         * listeners：监听器列表，用于监听和处理模型调用过程中的事件。
         */
        return OpenAiChatModel.builder()
                .apiKey("sk-75ab9e4c4cbf4d0fa8f405b8982ad8c8")
                .modelName("qwen-plus-2025-07-28")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .temperature(0.7)
                .maxTokens(4096)
                .presencePenalty(0.0)
                .strictJsonSchema(true)
                .timeout(Duration.ofSeconds(30))
                .maxRetries(3)
                .listeners(Arrays.asList(new ChatModeCustomerListener()))
                .logRequests(true)
                .logResponses(true)
                .build();
    }

    /**
     * 流式模型
     * @return
     */
    @Bean("qwenStream")
    public StreamingChatModel qwenStream() {
        return OpenAiStreamingChatModel.builder()
                .apiKey("sk-75ab9e4c4cbf4d0fa8f405b8982ad8c8")
                .modelName("qwen-plus-2025-07-28")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .temperature(0.7)
                .maxTokens(4096)
                .presencePenalty(0.0)
                .strictJsonSchema(true)
                .timeout(Duration.ofSeconds(300))
                .listeners(Arrays.asList(new ChatModeCustomerListener()))
                .logRequests(true)
                .logResponses(true)
                .build();
    }

    /**
     * 创建 DeepSeek 模型
     *
     * @return https://platform.deepseek.com/
     */
    @Bean("deepseek")
    public ChatModel chatModelDeepseek() {
        return OpenAiChatModel.builder()
                .apiKey("sk-3133ca49b0e443a3a49eb1d5614fc2de")
                .modelName("deepseek-reasoner")
                .baseUrl("https://api.deepseek.com/v1")
                .temperature(0.7)
                .maxTokens(4096)
                .presencePenalty(0.0)
                .strictJsonSchema(true)
                .timeout(Duration.ofSeconds(30))
                .maxRetries(3)
                .listeners(Arrays.asList(new ChatModeCustomerListener()))
                .logRequests(true)
                .logResponses(true)
                .build();
    }

    /**
     * 图片解析模型
     *
     * @return
     */
    @Bean("qwenImage")
    public ChatModel chatModelQwenImage() {
        return OpenAiChatModel.builder()
                .apiKey("sk-75ab9e4c4cbf4d0fa8f405b8982ad8c8")
                .modelName("qwen-vl-max")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .temperature(0.7)
                .maxTokens(4096)
                .presencePenalty(0.0)
                .strictJsonSchema(true)
                .timeout(Duration.ofSeconds(300))
                .maxRetries(3)
                .listeners(Arrays.asList(new ChatModeCustomerListener()))
                .logRequests(true)
                .logResponses(true)
                .build();
    }

    /**
     * 图片解析模型
     *
     * @return
     */
    @Bean("streamQwenImage")
    public StreamingChatModel streamChatModelQwenImage() {
        return OpenAiStreamingChatModel.builder()
                .apiKey("sk-75ab9e4c4cbf4d0fa8f405b8982ad8c8")
                .modelName("qwen-vl-max")
                .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
                .temperature(0.7)
                .maxTokens(4096)
                .presencePenalty(0.0)
                .strictJsonSchema(true)
                .timeout(Duration.ofSeconds(300))
                .listeners(Arrays.asList(new ChatModeCustomerListener()))
                .logRequests(true)
                .logResponses(true)
                .build();
    }
    @Bean("chatAssistant")
    public ChatAssistant chatAssistant() {
        return AiServices.create(ChatAssistant.class, chatModelQwen());
    }

    @Bean(name = "streamChatAssistant")
    public ChatAssistant streamChatAssistant() {
        return AiServices.builder(ChatAssistant.class).chatModel(chatModelQwen()).streamingChatModel(qwenStream()).build();
    }

}
